#!/usr/bin/env python
# -*- coding: utf-8 -*-


import sys, os
from PySide import QtCore, QtGui
import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
import noraejoe_daddy_rc
import re
import urllib

ORGANIZATION = "Jooncheol's Open Source Software"
VERSION = "1.0"
PROGRAMNAME = "Noraejoe daddy" + " " + VERSION

class NoraejoeDaddy(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.__c = QtCore.QSettings(QtCore.QSettings.NativeFormat, \
                QtCore.QSettings.UserScope, \
                ORGANIZATION, PROGRAMNAME)
        self.setWindowTitle(self.tr("Noraejoe::daddy")+" "+VERSION)
        self.setWindowIcon(QtGui.QIcon(":noraejoe-daddy.png"))
        self.__bg = QtGui.QPixmap(":noraejoe-daddy-bg.png")
        self.setWindowFlags(\
            QtCore.Qt.FramelessWindowHint|QtCore.Qt.WindowStaysOnTopHint)
        self.setMask(self.__bg.mask())
        self.resize(self.__bg.size())
        self.setAcceptDrops(True)
        self.__closeButtonPressed = False
        self.__dp = None

        self.__status_area = 30, 250, 200, 20
        self.__status_animation = None
        self.setComicsBalloon(None)

        geometry = self.__c.value("WindowGeometry", QtCore.QVariant())
        if not geometry.isNull():
            self.restoreGeometry(geometry.toByteArray())

    def keyPressEvent(self, event):
        if event.key()==QtCore.Qt.Key_Escape:
            self.close()
            return
        QtGui.QWidget.keyPressEvent(self, event)
    def mousePressEvent(self, event):
        if 200<event.x() and event.y()<60:
            self.__closeButtonPressed = True
            self.update(200, 0, 50, 60)
        else:
            self.__dp = event.x(), event.y()
            self.setComicsBalloon(self.tr("Move! move!"))

    def mouseReleaseEvent(self, event):
        self.__dp = None
        if self.__closeButtonPressed:
           self.__closeButtonPressed = False
           self.update(200, 0, 50, 60)
           if (200>event.x() or event.x()>self.width()) or \
               (event.y()>60 or event.y()<0):
               return
           self.close()
        else:
            QtGui.QWidget.mouseReleaseEvent(self, event)
            self.setComicsBalloon(None)

    def mouseMoveEvent(self, event):
        if not self.__dp:
            return
        gp = self.mapToGlobal(event.pos())
        self.move(gp.x()-self.__dp[0], gp.y()-self.__dp[1])

    def __slotSetDefaultComicsBalloon(self):
        self.setComicsBalloon(None)

    def setDefaultComicsBalloon(self, timeout):
        QtCore.QTimer.singleShot(timeout, self.__slotSetDefaultComicsBalloon)

    def setComicsBalloon(self, text):
        if not text:
            text=self.tr("Drag and drop URL link that contains swf animation")
        self.__status = text
        textwidth = QtGui.QFontMetrics(QtGui.QFont()).width(text)
        if textwidth > self.__status_area[2]:
            self.__status_animation = textwidth, 0
            QtCore.QTimer.singleShot(2000, self.__slotAnimationBalloon)
        else:
            self.__status_animation = None
        apply(self.repaint, self.__status_area)

    def __slotAnimationBalloon(self):
        if not self.__status_animation:
            return
        textwidth, additional_width = self.__status_animation
        if self.__status_area[2]+additional_width>=textwidth:
            additional_width = 0
        else:
            additional_width += 2
        self.__status_animation = textwidth, additional_width

        if additional_width==0 or \
            self.__status_area[2]+additional_width>=textwidth:
            QtCore.QTimer.singleShot(2000, self.__slotAnimationBalloon)
        else:
            QtCore.QTimer.singleShot(150, self.__slotAnimationBalloon)
        apply(self.repaint, self.__status_area)

    def paintEvent ( self, event):
        p = QtGui.QPainter(self)
        p.setClipRegion(event.region())
        p.setRenderHint(QtGui.QPainter.Antialiasing, True)
        p.drawPixmap(0, 0, self.__bg)

        if self.__status_animation:
            textwidth, additional_width = self.__status_animation
            rect = QtCore.QRectF(\
                    self.__status_area[0] - additional_width,
                    self.__status_area[1],
                    self.__status_area[2] + additional_width,
                    self.__status_area[3])
            p.drawText(rect, QtCore.Qt.AlignLeft, self.__status);
        else:
            rect = apply(QtCore.QRectF, self.__status_area)
            p.drawText(rect, QtCore.Qt.AlignCenter, self.__status);

        grey = QtGui.QColor(0xaa, 0xaa, 0xaa)
        lightgrey = QtGui.QColor(0xcc, 0xcc, 0xcc)
        color = grey
        if self.__closeButtonPressed:
            color = lightgrey
        b = QtGui.QBrush(color, QtCore.Qt.SolidPattern)
        p.setBrush(b)
        p.drawEllipse ( 205, 8, 47, 47 )

        pen = QtGui.QPen()
        #p.setBrush(QtCore.Qt.NoBrush)
        pen.setColor(QtGui.QColor(0xaa, 0xaa, 0xaa))
        p.setPen(pen)

        pen.setWidth(5)
        pen.setColor(QtGui.QColor(0, 0, 0))
        pen.setCapStyle(QtCore.Qt.RoundCap)
        p.setPen(pen)
        p.drawLine(217, 21, 238, 42)
        p.drawLine(238, 21, 217, 42)





    def dragEnterEvent(self, event):
        url = str(event.mimeData().text().toUtf8())
        if event.mimeData().hasText():
            event.acceptProposedAction()
            self.setComicsBalloon(self.tr("Drop to me!"))
        else:
            event.ignore()
            self.setComicsBalloon(self.tr("This is not a URL Link!"))
            self.setDefaultComicsBalloon(2000)

    def dragLeaveEvent(self, event):
        QtGui.QWidget.dragLeaveEvent(self, event)
        self.setComicsBalloon(None)

    def dropEvent(self, event):
        if event.mimeData().hasText():
            self.__url = str(event.mimeData().text().toUtf8())
            QtCore.QTimer.singleShot(0, self.__openLater)
            self.setComicsBalloon(self.tr('Processing ...'))
            event.accept()
        else:
            event.ignore()
    def __findSwfFromHTML(self):
        try:
            c = urllib.urlopen(self.__url)
        except:
            self.setComicsBalloon(self.tr('Could not found swf from URL'))
            self.setDefaultComicsBalloon(3000)
            return 
        html = c.read()
        cp = re.compile('http://[a-zA-Z0-9_\-\~/\.%]+\.swf')
        m = cp.findall(html.replace('\r','').replace('\n',''))
        if not m:
            self.setComicsBalloon(self.tr('Could not found swf from URL'))
            self.setDefaultComicsBalloon(3000)
            return 
            
        items = QtCore.QStringList()
        for x in m:
            if not items.contains(x):
                items.append(x)
        if items.count()>1:
            item, ok = QtGui.QInputDialog.getItem(self, self.tr("There are many different URLs of swf animation."), self.tr("Choose"), items, 0, False);
            if not ok:
                self.setComicsBalloon(self.tr('Canceled'))
                self.setDefaultComicsBalloon(3000)
                return;
            swfpath = str(item.toUtf8())
        else:
            swfpath = str(items[0].toUtf8())
        return swfpath
    def __openLater(self):
        tmpoutput = QtCore.QDir.tempPath ()+'/output.mp3'
        if self.__url[:-4]=='.swf':
            swfpath = self.__url
        else:
            swfpath = self.__findSwfFromHTML()
            if not swfpath:
                return

        c = urllib.urlopen(swfpath)
        tmpswf = QtCore.QDir.tempPath () + '/output.swf'
        open(tmpswf,'wb').write(c.read())
        result = os.popen('swfextract %s' % tmpswf).read()
        cp=re.compile('1 MP3')
        mp3 = cp.search(result)
        sound = re.compile('.+ Sound.*: ID\(s\) ([0-9, ]+)').search(result)

        if not mp3 and not sound:
            os.unlink(tmpswf)
            self.setComicsBalloon(self.tr('Could not found audio from swf'))
            self.setDefaultComicsBalloon(3000)
            return

        if mp3:
            cmd = 'swfextract -o %s -m %s' % (tmpoutput, tmpswf)
            ret = os.popen(cmd).read()
            if not ret.startswith('NOTICE') and not sound:
                os.unlink(tmpswf)
                self.setComicsBalloon(ret.strip())
                self.setDefaultComicsBalloon(3000)
                return
            if ret.startswith('NOTICE'):
                self.save(tmpoutput)
                return
        if sound:
            ids = sound.groups()[0].split(',')
            if len(ids)>1:
                items = QtCore.QStringList()
                for x in ids:
                    items.append('Sound ID: '+x.strip())
                item, ok = QtGui.QInputDialog.getItem(self, self.tr("There are many sound objects."), self.tr("Choose"), items, 0, False);
                if not ok:
                    self.setComicsBalloon(self.tr('Canceled'))
                    self.setDefaultComicsBalloon(3000)
                    return;
                id = str(item.toUtf8()).split(':')[1].strip()
            else:
                id = ids[0].strip()
            cmd = 'swfextract -o %s -s %s %s' % (tmpoutput, id, tmpswf)
            ret = os.popen(cmd).read()
            os.unlink(tmpswf)
            bin = open(tmpoutput).read(10)
            is_mp3 = bin.startswith('ID3')
            if not is_mp3:
                import struct
                a = struct.unpack('!H', bin[:2])[0] & 0xfffe
                if a in (0xfffa, 0xfff2):
                    is_mp3 = True
            if not is_mp3:
                os.unlink(tmpoutput)
                self.setComicsBalloon(self.tr('Could not found mp3 from swf'))
                self.setDefaultComicsBalloon(3000)
                return
            self.save(tmpoutput)


    def save(self, audio):
        saveddir = self.__c.value("DefaultPath", QtCore.QVariant())
        defaultdir = QtCore.QDir.homePath()
        if not saveddir.isNull():
            defaultdir = saveddir.toString()


        abspath = QtGui.QFileDialog.getSaveFileName (self, 
                self.tr('Save mp3 file'), defaultdir+'/output.mp3', 
                self.tr("MP3 (*.mp3)"))
        if abspath:
            utf8path = str(abspath.toUtf8())
            os.rename(audio, utf8path)
            self.setComicsBalloon(self.tr('Save completed!'))
            self.setDefaultComicsBalloon(3000)
            fi = QtCore.QFileInfo(abspath)
            dirname = fi.absoluteDir().path()
            self.__c.setValue("DefaultPath", QtCore.QVariant(dirname))
        else:
            os.unlink(audio)
            self.setComicsBalloon(self.tr('Canceled'))
            self.setDefaultComicsBalloon(3000)

    def closeEvent(self, event):
        geometry = self.saveGeometry()
        self.__c.setValue("WindowGeometry", QtCore.QVariant(geometry))
        self.__c.sync()
        QtGui.QWidget.closeEvent(self, event)
        



if __name__ == "__main__":

    app = QtGui.QApplication(sys.argv)
    translator = QtCore.QTranslator()
    if os.environ.has_key('LANG') and os.environ['LANG'].startswith('ko'):
        translator.load("noraejoe-daddy-ko.qm")
    QtGui.qApp.installTranslator(translator)
    w = NoraejoeDaddy()
    w.show()
    sys.exit(app.exec_())

# vim600: sw=4 ts=8 sts=4 et bs=2 fdm=marker fileencoding=utf8 encoding=utf8
